Skip to main content

Grid Basics

The grid is a layout system that allows you to create complex and responsive grid-based designs. It provides a way to divide the web page into rows and columns, making it easier to position and align elements.

I. Introduction to Grid

Resource

1. Setting up a Grid

1. Grid container

We can think about CSS Grid in terms of containers and items. When you make an element a grid container, it will “contain” the whole grid. In CSS, an element is turned into a grid container with the property display: grid or display: inline-grid.

Note: Only the direct child elements will become grid items here. If we had another element as a child under one of these child elements it would not be a grid item.

<!-- index.html -->
<div class="container">
<div>Item 1</div>
<div>Item 2
<p>I am not a grid item!</p>
</div>
<div>Item 3</div>
<div>Item 4</div>
</div>
.container {
display: grid;
}

2. Columns and Rows

Columns are the vertical tracks in a grid layout. They are defined using the grid-template-columns property.

.container {
display: grid;
grid-template-columns: 200px 100px 300px;
/* Three column tracks with widths 200px, 100px, and 300px */
}

Rows are the horizontal tracks in a grid layout. They are defined using the grid-template-rows property.

.container {
display: grid;
grid-template-rows: 50px 100px auto;
/* Three row tracks with heights 50px, 100px, and auto */
}

The grid-template property is a shorthand for defining both columns and rows together. The columns are specified after the forward-slash (/), and the rows are defined before the slash.

.container {
display: grid;
grid-template: 50px 100px / 200px 50px 100px;
/* Two row tracks (50px, 100px) and three column tracks (200px, 50px, 100px) */
}

2. Explicit vs. Implicit Grid

Resource

Explicit grid tracks are the ones you define directly using the grid-template-columns and grid-template-rows properties. These properties allow you to specify the size and number of columns and rows in your grid layout.

Implicit grid tracks are automatically created by the grid layout when there are more grid items than the explicit grid tracks can accommodate. These implicit tracks are added as needed to fit the extra grid items. By default, the size of implicit grid tracks is determined by the grid-auto-rows and grid-auto-columns properties.

.container {
display: grid;
grid-template-rows: 30px 100px; /* Two explicit row tracks */
grid-auto-rows: 80px; /* Size of implicit row tracks */
}

3. Gap

The gap between grid rows and columns is known as the gutter or alley. Gap sizes can be adjusted separately for rows and columns using the column-gap and row-gap properties.

.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
row-gap: 20px; /* Gap between rows */
column-gap: 30px; /* Gap between columns */
}

Furthermore, we can use a shorthand property called gap to set both row-gap and column-gap.

.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 20px 30px; /* row-gap: 20px, column-gap: 30px */
}

II. Positioning Grid Items

Resource

1. Grid Lines

Grid lines are the horizontal and vertical lines that divide the grid into rows and columns, respectively. They are created implicitly when you define grid tracks (rows and columns) and they cannot be explicitly created. Grid lines are numbered starting from 1, and they are used to position grid items within the grid layout. They are what we use to position grid items.

.container {
display: grid;
grid-template-columns: 50px 100px; /* Creates 3 vertical grid lines (1, 2, 3) */
grid-template-rows: 100px 200px; /* Creates 3 horizontal grid lines (1, 2, 3) */
}

2. Grid Cells

A grid cell is the intersection of a row track and a column track. It represents a single unit of space within the grid layout. Each grid cell can contain one or more grid items, depending on how the items are positioned and sized.

3. Positioning

  • grid-column-start: This property specifies the grid line where the item should start in the grid column. The grid lines are numbered from 1 (for the start edge of the grid) to (n+1) (for the end edge).
  • grid-column-end: This property specifies the grid line where the item should end in the grid column.
  • grid-column: This shorthand property sets both the grid-column-start and grid-column-end in a single declaration.
.item {
grid-column-start: 2; /* Start at the 2nd grid line */
grid-column-end: 4; /* End at the 4th grid line */
}

/* equivalent to */
.item {
grid-column: 2 / 4; /* Start at the 2nd line, end at the 4th line */
}
  • grid-row-start: This property specifies the grid line where the item should start in the grid row.
  • grid-row-end: This property specifies the grid line where the item should end in the grid row.
  • grid-row: This shorthand property sets both the grid-row-start and grid-row-end in a single declaration.
.item {
grid-row-start: 1; /* Start at the 1st grid line */
grid-row-end: 3; /* End at the 3rd grid line */
}

/* equivalent to */
.item {
grid-row: 1 / 3; /* Start at the 1st line, end at the 3rd line */
}

4. grid-area

The grid-area property is a shorthand property that defines a grid item's position and size within the grid container. It can be used in two different ways:

1. Positioning with Grid Line Numbers

  • The grid-area property can be used to specify the grid lines where the grid item should start and end, both horizontally and vertically.
  • The syntax is grid-area: row-start / column-start / row-end / column-end;
.item {
grid-area: 1 / 2 / 4 / 6; /* Starts at row 1, column 2; ends at row 4, column 6 */
}

2. Naming Grid Areas

  • The grid-area property can also be used to assign a name to a grid item.
  • This name can then be referenced in the grid-template-areas property of the grid container to define the layout of the grid visually.

In the example, the grid layout is defined using the named grid areas, and the period (.) represents an empty cell in the grid.

.living-room {
grid-column: living-room
}

.kitchen {
grid-area: kitchen;
}

.toilet {
grid-area: toilet;
}

.closet {
grid-area: closet;
}

.container {
/* grid */
display: grid;
grid-template-columns: 20vw auto 15vw;
grid-template-rows: 20vh 40vh auto;

/* naming grid-areas */
grid-template-areas:
"living-room living-room living-room"
"kitchen bedroom toilet"
"kitchen closet toilet";
}

III. Other Grid Properties

Resource

1. Fractional Units

The most basic way to make grid items dynamic is by using fractional units (fr). This unit distributes the remaining space in a grid container after allocating space to any grid tracks with a fixed size. When multiple grid tracks are assigned fr values, the available space is divided according to the ratio of those fr values.

/* All columns have equal width */
grid-template-columns: 1fr 1fr 1fr;

/* The second column is three times wider than the others */
grid-template-columns: 1fr 3fr 1fr;

/* A mix of fixed and fractional sizes */
grid-template-columns: 200px 1fr 150px 2fr;

2. resize

The resize property is used to specify whether an element is resizable by the user, and if so, in what direction(s) it can be resized.

  • none: the default value, the element cannot be resized by the user.
  • both: allows the user to resize the element both horizontally and vertically by dragging the element’s bottom-right corner.
  • horizontal: allows the user to resize the element horizontally by dragging the element’s right edge.
  • vertical: allows the user to resize the element vertically by dragging the element’s bottom edge.
.container {
display: grid;
resize: both;
overflow: auto; /* to enable scrolling if we resize the container to be smaller than our grid can accommodate */
}

3 .repeat()

The repeat() function is used to create repeating patterns of grid tracks (rows or columns) within a grid container.

repeat(repetitions, size)
  • repetitions: This can be either a positive integer value representing the number of times to repeat the track size, or the keyword auto-fill or auto-fit.
  • size: This can be a length value (e.g., 20px, 1fr), a percentage value, or a flexible length (minmax(min, max)).
grid-template-columns: repeat(4, 200px);
/* Creates 4 columns, each with a width of 200px */

grid-template-columns: repeat(2, 150px) repeat(3, 100px);
/* Creates 5 columns: 2 with width 150px, followed by 3 with flexible width of 1fr */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* Creates as many columns as possible with a minimum width of 200px and a maximum width of 1fr, based on the available space */

grid-template-rows: repeat(auto-fit, minmax(100px, auto));
/* Creates as many rows as needed to fit the content, with a minimum height of 100px and a maximum height determined by the content */

4. Minimum and Maximum Track Sizes

Example: The grid rows will have a size of 100px, the smallest value from the list (100px, 200px, 300px, 400px, 500px).

Example: A grid with 2 rows and 5 columns. The row heights will be either 200px or 50% of the container's height (whichever is smaller), and the column widths will be either 120px or 15% of the container's width (whichever is larger).

.grid-container {
grid-template-rows: repeat(2, min(200px, 50%));
grid-template-columns: repeat(5, max(120px, 15%));
}

5. Dynamic Minimum and Maximum Sizes

1. minmax()

This function is specifically used with Grid Layout. It defines a size range for grid tracks, allowing them to grow or shrink within a specified minimum and maximum size.

Syntax: minmax(min-size, max-size).

  • min-size: The minimum size the grid track can be. It can be a length value (e.g., 150px) or a flexible value like min-content, max-content, or a percentage.
  • max-size: The maximum size the grid track can be. It can be a length value (e.g., 200px) or a flexible value like min-content, max-content, or a percentage.

The function is used with the following CSS properties:

  • grid-template-columns
  • grid-template-rows
  • grid-auto-columns
  • grid-auto-rows

Example: The grid container will have 5 columns, and each column track will have a minimum width of 150px and a maximum width of 200px.

  • If the grid container is wider, the column tracks will grow up to 200px, but not beyond that.
  • If the grid container is narrower, the column tracks will shrink down to 150px, but not smaller.
.grid-container {
grid-template-columns: repeat(5, minmax(150px, 200px));
}

2. clamp()

This function allows constraining a value within a specified range.

Syntax: clamp(min-size, ideal-size, max-size)

  • min-size: The minimum size the element can be.
  • ideal-size: The preferred size the element should be if possible.
  • max-size: The maximum size the element can be.

The function can be used anywhere, not just within a grid container, such as width, height, font-size, padding, margin, etc.

Example: The grid container will have 5 column tracks. Initially, each column track will try to be 20% of the container’s width (preferred value).

  • If the 20% width is less than 150px, the column tracks will be set to 150px.
  • If 20% of the container’s width is greater than 200px, the column tracks will be set to 200px.
.grid-container {
grid-template-columns: repeat(5, clamp(150px, 20%, 200px));
}

6. auto-fit and auto-fill

Resource

1. auto-fit

auto-fit is a value used with the repeat() function. It creates as many grid tracks (rows or columns) as possible while respecting the max-content size of the grid items, not overflowing the grid container, and stretching the remaining grid tracks to fill the available space.

Syntax: repeat(auto-fit, size)

  • auto-fit can also be used with minmax() to define the size range for the grid tracks.
  • The grid tracks will stretch to fill the available space, up to the max-size specified in minmax().

**Example 1: ** The grid will create as many 200px wide columns as can fit within the container's width.

.grid-container {
grid-template-columns: repeat(auto-fit, 200px);
}

Example 2: The grid container will create as many columns as possible, with a minimum width of 100px and a maximum width of 300px.

.grid-container {
/* fit as many columns as possible, each column has the min-width of 100px
when the page expands, each column can grow up to a max of 300px */
grid-template-columns: repeat(auto-fit, minmax(100px, 300px));
}

2. auto-fill

auto-fill is also a value used with the repeat() function. It creates as many grid tracks (rows or columns) as possible to fill the entire grid container, adding implicit grid tracks if needed, even if there are no grid items to fill them.

Syntax: repeat(auto-fill, size)

  • auto-fill can also be used with minmax() to define the size range for the grid tracks.
  • The grid tracks will stretch to fill the available space, up to the max-size specified in minmax().

**Example: ** The grid will create as many rows as needed to fill the container's height, with each row having an equal 1fr height.

.grid-container {
grid-template-rows: repeat(auto-fill, 1fr);
}

Difference between auto-fit and auto-fill

  • auto-fit creates only as many grid tracks as needed to fit the grid items.
  • auto-fill creates as many grid tracks as needed to fill the entire grid container, even if there are no grid items to fill the remaining tracks.

As seen in the demonstration image below, auto-fit doesn’t create any more tracks after Item 3, but auto-fill creates 3 more tracks to fill the entire grid, even though there are no more items to fill the remaining tracks.

7. Alignment

1. align-self

The align-self property is primarily used in Flexbox and Grid layouts. It allows controlling the alignment of an individual child element along the parent container's cross-axis (perpendicular to the main axis).

2. justify-self

The justify-self property is primarily used in Flexbox and Grid layouts. It allows controlling an individual child element's justification (alignment along the main axis) within the parent container.

While align-self and justify-self can be used on elements with a normal block-level layout (e.g., display: block), their effects will be limited. For optimal alignment control, it is recommended to use them with Flexbox or Grid layouts.

IV. Flexbox and Grid

Resources

1. Flexbox vs. Grid

Resource

1. One-dimension vs. Two-dimensions

  • One-dimensional content: If you have content that needs to be positioned or aligned in a single dimension (either horizontally or vertically), Flexbox can make it easier to control how that content is positioned within a Flex container.
  • Two-dimensional layout: If you want to accurately place content in a complex two-dimensional layout (both horizontally and vertically), Grid can be easier to use.

2. Content vs. Layout

  1. Content-first Design:
    • In Flexbox, the content shapes the layout. The layout adapts and responds to the content within the flex container.
    • Flexbox is well-suited for this approach because it provides control over the behavior of items (how they grow, shrink, their ideal size, and position in relation to each other) through logical rules based on the content.
    • Flexbox layouts are dynamic, and the final layout is a consequence of the content and the flex container's dimensions.
  2. Layout-first Design
    • In Grid, the layout shapes the content inside. The content must fit within the defined grid structure.
    • Grid is an excellent choice for this approach because it gives you full control over the layout by defining grid row and column tracks.
    • Content in a grid can only fill the spaces of explicit or implicit tracks, allowing you to define the overall layout structure first.

2. Combining Flexbox and Grid

If you want your overall layout to be a grid but want the grid items themselves to act as flex containers, you can nest Flexbox inside Grid. This allows you to benefit from the precise two-dimensional placement that Grid offers for the overall layout while also enabling the content inside each grid item to freely move and align using Flexbox.